﻿using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Sasa.QualityTools.CodeAnalysis.Core.Models;
using Sasa.QualityTools.CodeAnalysis.Core.Utilities;
using Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.ViewModels;
using Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.Views;
using Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.VisualStudio;
using System;
using System.IO;
using System.Windows.Forms;
using Sasa.QualityTools.CodeAnalysis.Common;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.EventHandlers
{
    [Obsolete]
    internal static class BuildEventHandler
    {
        private static bool isInitialized = false;


        private static Ide Ide { get; set; }

        private static FxCopIntegratorPackage Package { get; set; }


        internal static void Initialize(FxCopIntegratorPackage package)
        {
            if (isInitialized) return;

            Ide = new Ide(package);
            Package = package;

            var dte = (DTE)((IServiceProvider)package).GetService(typeof(DTE));
            dte.Events.BuildEvents.OnBuildBegin += OnBuildBegin;
            dte.Events.BuildEvents.OnBuildProjConfigDone += OnBuildProjConfigDone;
            dte.Events.BuildEvents.OnBuildDone += OnBuildDone;
        }

        private static void OnBuildBegin(vsBuildScope scope, vsBuildAction action)
        {
            Logger.Info("Resetting view model of Code Analysis Result window.");

            var viewModel = new CodeInspectionResultViewModel();

            viewModel.CodeFocusRequested += (sender, e) =>
            {
                if (e.Path != null)
                {
                    Ide.Solution.Open(e.Path, e.Line);
                }
            };

            //viewModel.ShowRuleRequired += (sender, e) =>
            //{
            //    var rulePane = Ide.ShowToolWindowPane<RuleDetailWindowPane>();
            //    ((RuleDetailContent)rulePane.Content).DataContext = e.Rule;
            //};

            var pane = Ide.FindToolWindowPane<CodeInspectionResultWindowPane>();
            ((CodeInspectionResultContent)pane.Content).DataContext = viewModel;
        }

        private static void OnBuildProjConfigDone(string projectUniqueName, string projectConfig, string platform, string solutionConfig, bool success)
        {
            var project = Ide.Solution.FindProjectByUniqueName(projectUniqueName);

            if (!success)
            {
                Logger.Warn("FxCop Integrator didn't perform code analysis because {0} project coundn't build.", project.Name);
                return;
            }

            var config = CodeAnalysisConfiguration.Load(project.ConfigurationPath);
            config.Override(CodeAnalysisConfiguration.Load(project.Solution.ConfigurationPath));
            //if (!config.EnableCodeAnalysisOnBuild)
            //{
            //    Logger.Info("FxCop Integrator didn't perform code analysis because {0} project was disabled 'Code Analysis on Build'.", project.Name);
            //    return;
            //}

            var dte = (DTE)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(DTE));
            var analysis = new Core.Models.CodeInspector();
            analysis.CommandPath = Package.GeneralOption.FxCopCmdPath;
            analysis.CommandOption = FxCopCmdOptionBuilder.Build(project, Package.GeneralOption.FxCopVersion);
            try
            {
                analysis.PerformCodeAnalysis();
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Failed to perform code analysis.");
                dte.ExecuteCommand("Build.Cancel");
                var message = "Build have been broken because code analysis failed when " + project.Name + " project analyzed.";
                MessageBox.Show(message, "FxCop Integrator broke build", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
                return;
            }

            var pane = Ide.FindToolWindowPane<CodeInspectionResultWindowPane>();
            var viewModel = (CodeInspectionResultViewModel)((CodeInspectionResultContent)pane.Content).DataContext;
            foreach (var problem in analysis.Report.Problems)
            {
                var p = new ProblemViewModel(problem);
                if (problem.AssemblyPath != null)
                {
                    p.ProjectName = project.Name;
                }
                if (p.Path == null && p.TypeName != null)
                {
                    p.Path = project.GetFilePathFromTypeName(p.TypeName);
                }
                viewModel.Rows.Add(p);
            }
            //foreach (var rule in analysis.Report.Rules)
            //{
            //    viewModel.Rules[rule.CheckId] = new RuleViewModel(rule);
            //}

            if (!File.Exists(project.AssemblyPath + ".lastcodeanalysissucceeded"))
            {
                dte.ExecuteCommand("Build.Cancel");
                var message = "Build have been broken because FxCop Integrator found error level violation in " + project.Name + " project.";
                Logger.Info(message);
                MessageBox.Show(message, "FxCop Integrator broke build", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
            }
        }

        private static void OnBuildDone(vsBuildScope scope, vsBuildAction action)
        {
            Logger.Info("Showing Code Analysis Result window.");

            var pane = Ide.FindToolWindowPane<CodeInspectionResultWindowPane>();
            var viewModel = (CodeInspectionResultViewModel)((CodeInspectionResultContent)pane.Content).DataContext;
            if (viewModel.Rows.Count > 0)
            {
                Ide.ShowToolWindowPane<CodeInspectionResultWindowPane>();
                viewModel.GoToFirstPage();
            }
        }
    }
}
